package com.wpp;

import org.junit.Test;

import java.util.*;

/*
 *   Map:双列数据，存储具有key-value对的数据
 *       HashMap:作为map的主要实现类；线程不安全的，但是效率高；可以存储null的key或者value
 *           LinkedHashMap:保证在遍历map元素时，可以按照添加的顺序实现遍历
 *                   原因：在原有的HashMap底层结构基础上，添加了一对指针，指向前一个或者后一个元素
 *                   对于频繁的遍历操作，此类执行效率高于HashMap.
 *       TreeMap:保证按照添加的key-value进行排序，实现排序遍历，此时考虑的是自然排序或定制排序，
 *           底层结构使用的是红黑树，且key必须是由同一个类创建的对象
 *       Hashtable:作为古老的实现类，线程安全的，效率低，不可以存储null的key或者value
 *           Properties:常用来处理配置文件，key和value都是String类型
 *   HashMap的底层：数据+链表    (jdk7及之前)
 *                 数据+链表+红黑树    (jdk8)
 *Map结构的理解：
 *   Map中的key:无序的，不可重复的，使用Set存储所有的key。---->key所在的类要重写equals()和hashcode();
 *   Map中的value：无序的，可重复的，使用collection存储所有的value
 *   一个键值对：key-value构成了一个entry对象
 *   Map中的entry：无序的，不可重复的，使用set存储所有的entry
 *
 * HashMap的底层实现原理：jdk7
 *   HashMap hashMap = new HashMap();
 *   在实例化以后，底层创建了长度是16的一维数组entry[] table;
 *   map.put(key1,value1);
 *   首先，调用key1所在类的hashcode()计算哈希值，此哈希值经过算法计算以后，得到在entry数组中的存放位置
 *   如果此位置上的数据为空，此时的key1-value1添加成功
 *   如果此位置上的数据不为空，此位置上存在一个或者多个数据(以链表形式存在),比较key1和已经存在的一个或多个数据的哈希值：
 *       如果key1的哈希值与已经存在的数据的哈希值都不相同，此时key1-value1添加成功
 *       如果key1的哈希值与已经存在的数据的哈希值相同，则继续比较：调用key1所在类的equals()方法，比较：
 *           如果返回false,此时key1-value1添加成功
 *           如果返回true,使用value1替换原来的数据，此时的put也就是个修改功能
 *
 *   在不断的添加过程中，会涉及到扩容问题
 *       默认的扩容方式为：当超出临界值时，扩容为原来的2倍，并把原来的数据复制到新的数组中
 * jdk8相比较jdk7在底层实现方面的不同：
 *  1.new HashMap();底层没有创建一个长度为16的数组
 *  2.jdk 8 底层的数组是Node[],而非entry数组
 *  3.首次调用put方法时，底层才创建长度为16的数组
 *  4.jdk7的底层结构只有：数组+链表  jdk8中底层结构：数组+链表+红黑树
 *       (jdk8)当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64时；此时索引位置上的所有数据 改为使用红黑树进行存储
 *   默认加载因子：0.75
 *   默认临界值：16 * 0.75 = 12
 *   链表长度大于：8 转化为红黑树
 *   Node被树化时最小的hash表容量为64
 *
 *   LinkedHashMap的底层实现原理？
 *       LinkedHashMap中的entry能够记录添加的元素的先后顺序
 *问题思考？
 *   1.HashMap的底层实现原理？
 *   2.HashMap和Hashtable的异同？
 *   3.CurrentHashMap 与HashMap的异同？
 *
 *
 * */
public class MapTest {

    //常用方法测试
    @Test
    public void test() {
        HashMap hashMap = new HashMap();
        hashMap.put("aa", 12);
        hashMap.put("bb", 12);
        hashMap.put("aa", 1112);
        hashMap.put("cc", 1672);

        System.out.println(hashMap);

        //hashMap.clear();
        System.out.println(hashMap);

        boolean empty = hashMap.isEmpty();
        System.out.println(empty);

        int size = hashMap.size();
        System.out.println(size);

        boolean aa = hashMap.containsKey("aa");
        System.out.println(aa);

        Object aa1 = hashMap.get("aa");
        System.out.println(aa1);

        Set set = hashMap.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        System.out.println();

        Collection values = hashMap.values();
        Iterator iterator1 = values.iterator();
        while (iterator1.hasNext()) {

            System.out.println(iterator1.next());
        }

        Set set1 = hashMap.entrySet();
        Iterator iterator2 = set1.iterator();
        while (iterator2.hasNext()) {

            System.out.println(iterator2.next());
        }
    }


    /*
     * TreeMap：
     *   向TreeMap中添加key-value，要求key必须是由同一个类创建的对象
     *   因为要按照key进行排序:自然排序、定制排序
     *
     * */

    @Test
    public void test2() {

        TreeMap treeMap = new TreeMap();
        Hashtable<Object, Object> objectObjectHashtable = new Hashtable<>();
        treeMap.put("cc", 31);
        treeMap.put("aa", 323);
        treeMap.put("bb", 324);
        treeMap.put("dd", 132);
        System.out.println(treeMap);
    }
}
